package com.sl.core.engine.plugin.loader.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.google.common.collect.Maps;
import com.sl.core.engine.classloader.ProcessClassLoader;
import com.sl.core.engine.plugin.domain.PluginDecorate;
import com.sl.core.engine.plugin.loader.ProcessPluginLoader;
import org.apache.commons.compress.utils.Lists;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;

public abstract class AbstractProcessPluginLoader implements ProcessPluginLoader {


    public Map<String, List<PluginDecorate>> loader(ClassLoader classLoader) {
        Map<String, List<PluginDecorate>> pluginStoreMap = new HashMap<>();
        //从当前classLoader中找，这种情况只可能存在一种 就是最新的
        Map<String, Map<String, String>> config = getConfig(classLoader);
        //开始获取插件信息
        for (Map.Entry<String, Map<String, String>> entry : config.entrySet()) {
            String k = entry.getKey();
            Map<String, String> v = entry.getValue();
            PluginDecorate pluginDecorate = BeanUtil.copyProperties(v, PluginDecorate.class);
            pluginDecorate.setFileUrl(k);
            pluginDecorate.setClassLoader(classLoader);
            String pluginCode = pluginDecorate.getPluginCode();
            if (StrUtil.isBlank(pluginCode)) {
                continue;
            }
            if (StrUtil.isBlank(pluginDecorate.getGroupCode())) {
                pluginDecorate.setGroupCode(PinyinUtil.getPinyin(pluginDecorate.getGroupName(),""));
            }
            //如果插件名相同做覆盖
            List<PluginDecorate> pluginDecorates = pluginStoreMap.computeIfAbsent(pluginCode, (va) -> Lists.newArrayList());
            pluginDecorates.add(pluginDecorate);
        }

        return pluginStoreMap;
    }


    public Map<String, List<PluginDecorate>> getPluginStoreMap(Map<String, List<PluginDecorate>> loader) {
        if (MapUtil.isEmpty(loader)) {
            return Maps.newHashMap();
        }
        Map<String, List<PluginDecorate>> cv = Maps.newHashMap();

        for (Map.Entry<String, List<PluginDecorate>> entry : loader.entrySet()) {
            String key = entry.getKey();
            List<PluginDecorate> value = entry.getValue();

            List<PluginDecorate> pluginDecorates = BeanUtil.copyToList(value, PluginDecorate.class);
            cv.put(key, pluginDecorates);
        }
        return cv;
    }


    protected Map<String, Map<String, String>> getConfig(ClassLoader classLoader) {
        //开始自动查找
        Map<String, Map<String, String>> result = MapUtil.newHashMap();
        try {
            Enumeration<URL> urls = null;

            if (classLoader instanceof ProcessClassLoader cl) {
                urls = cl.getResources("plugin.properties", false);
            } else {
                urls = classLoader.getResources("plugin.properties");
            }

            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                EncodedResource encodedResource = new EncodedResource(resource, Charset.defaultCharset());
                Properties properties = PropertiesLoaderUtils.loadProperties(encodedResource);

                Map<String, String> res = new HashMap<>();
                properties.forEach((k, v) -> {
                    res.computeIfAbsent(k.toString(), key -> StrUtil.trim(StrUtil.str(v.toString(), Charset.defaultCharset())));
                });
                result.put(url.toString(), res);
            }

        } catch (IOException exception) {
            throw new IllegalArgumentException("Unable to load properties from location [resources/plugin.properties]", exception);
        }
        return result;
    }

}
